-
Notifications
You must be signed in to change notification settings - Fork 30.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lib/net: Convert to using internal/errors #14782
Conversation
doc/api/errors.md
Outdated
@@ -1004,6 +1004,22 @@ Used when a callback is called more then once. | |||
can either be fulfilled or rejected but not both at the same time. The latter | |||
would be possible by calling a callback more then once. | |||
|
|||
<a id="ERR_NET_INVALID_LISTEN_ARG"></a> | |||
### ERR_NET_INVALID_LISTEN_ARG |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason not to use the existing ERR_INVALID_ARG_TYPE
instead of creating this new error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is an ongoing debate on whether error codes should be very specific (like this case), or more general (like what @Trott is suggesting)
For now the trend is towards a clear separation between bad arguments or options, and run time errors. But minimal separation between different argument errors.
@pmatzavin IMHO, the description you've given here should be in the net.Server.listen
API documentation, and ERR_INVALID_ARG_TYPE
is good enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Trott @refack I am having trouble using the 'ERR_INVALID_ARG_TYPE' for the
Server.prototype.listen()
in the lib/net.js
.
I am describing the problem below :
The Server.prototype.listen()
implementation
has some early return statements for the following cases:
options = options._handle || options.handle || options;
options instanceof TCP
typeof options.fd === 'number' && options.fd >= 0
(args.length === 0 || typeof args[0] === 'function' || (typeof options.port === 'undefined' && 'port' in options)) || typeof options.port === 'number' || typeof options.port === 'string'
options.path && isPipeName(options.path)
At the end, if none of these early return statements runs, then the error is thrown.
So I am having trouble using the
E('ERR_INVALID_ARG_TYPE', invalidArgType)
error.
As I cannot compute a suitable error message using the
invalidArgType(name, expected, actual)
(file: lib/internal/errors.js
) callback,
for the case that I described above.
I have not yet found a similar case in the source code.
That's why I used the new error ERR_NET_INVALID_LISTEN_ARG
in the first place.
Do you have any suggestions on how should I handle this case or on how should I use the ERR_INVALID_ARG_TYPE
error for this case?
Should I refactor the invalidArgType
method in the lib/internal/errors.js
to return a more generic error message (like: invalid type
)
if the expected
argument is not specified?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm understanding correctly, the error isn't (necessarily?) an invalid argument type, but an invalid argument.
If we can make ERR_INVALID_OPT_VALUE
work instead, that would be great. Will that result in a similar difficulty? If so, then I'm OK with a new error. If we've been trying for more general errors, E_INVALID_OPTION_OBJECT or something like that might be preferable so it can be re-used elsewhere. But there's a valid argument for specific codes too, so either way is fine by me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Trott I used the ERR_INVALID_OPT_VALUE
error instead of creating a new error.
I amended the change and pushed -f to the current pull request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @pmatzavin! Welcome and thanks for the PR! I left a question/suggestion for a change.
Hi @Trott! Thanks for the help and the suggestion. I am traveling right now without my laptop. I will update my PR by this Saturday. |
@nodejs/ctc This is semver-major, needs some CTC reviews. |
df9e7cc
to
2e0914e
Compare
updated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
(just some nits)
const prefix = '"port" option should be a number or string: '; | ||
const cleaned = opt.replace(/[\\^$.*+?()[\]{}|=!<>:-]/g, '\\$&'); | ||
return new RegExp(`^TypeError: ${prefix}${cleaned}$`); | ||
function portTypeError() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can replace this with:
const portTypeError = common.expectsError({
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError
}, 5);
and the same in L46
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@refack I have read the CONTRIBUTING.md
but I am not sure which of the following should I use to make the requested changes:
- amend the commit and push --force-with-lease
- git commit --fixup
- simply add a new commit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO simply add a commit, since it makes re-reviews easier.
A common practice is to prefix the new commit's message with [fixup] ...
so it's clear that it should be squashed when the PR is landed.
test/parallel/test-net-localerror.js
Outdated
assert.throws(() => { | ||
net.connect(opts); | ||
}, msg); | ||
function connect(opts, code, type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can now be:
const connect = (opts, code, type) => common.expectsError(
() => net.connect(opts),
{ code, type }
);
const assert = require('assert'); | ||
const common = require('../common'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually require('../common');
should be first. It does some wiring, and maybe we'll want it to monkeypatch assert
in the future.
Hello @pmatzavin and welcome. Thank you very much for the contribution 🥇 P.S. If you have any question you can also feel free to contact me directly (@ mention, email, IM, or IRC) |
lib/net.js
Outdated
throw new TypeError('options must be an object'); | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', | ||
'options', | ||
['object'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/[object']
/`Object'
When there is a single value, it doesn't need to be in an array
SGTM, but I defer to @jasnell on the integration with the full new error messaging approach, when he gives a +1 then consider mine in here too |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small non blocking nit
lib/net.js
Outdated
@@ -1485,7 +1497,9 @@ Server.prototype.listen = function() { | |||
return this; | |||
} | |||
|
|||
throw new Error('Invalid listen argument: ' + util.inspect(options)); | |||
throw new errors.TypeError('ERR_INVALID_OPT_VALUE', | |||
'listen options', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO this should be just options
so it will be rendered as:
The value "{ gaga: 4 }" is invalid for option "options"
which seems a tiny bit better then
https://github.com/nodejs/node/blob/77b02d2d8345c407dc0e0121420d823b2ce6fb18/test/parallel/test-net-server-listen-options.js#L63
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
@jasnell PTAL |
lib/net.js
Outdated
if (type === 'PIPE') return new Pipe(); | ||
if (type === 'TCP') return new TCP(); | ||
throw new TypeError('Unsupported fd type: ' + type); | ||
throw new errors.Error('ERR_INVALID_HANDLE_TYPE'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer the message to include the handle type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pmatzavin look at
Line 200 in cbd3708
E('ERR_INVALID_FD', '"fd" must be a positive integer: %s'); |
You can add just after it:
E('ERR_INVALID_FD_TYPE', 'Unsupported fd type: %s');
test/parallel/test-net-localerror.js
Outdated
const connect = (opts, code, type) => common.expectsError( | ||
() => net.connect(opts), | ||
{ code, type } | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesn't quite match our typical code format .... it should be something like
const connect = (opts, code, type) => {
common.expectsError(...);
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's my mistake.
@pmatzavin for arrow functions that span multiple lines, in node's code it's prefered to use the {}
syntax for extra clarity of the scope (even if it is just one expression like here).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few nits but generally LGTM
@refack There was no test for the fd error thrown in the |
lib/net.js
Outdated
} | ||
if (!isLegalPort(port)) { | ||
throw new RangeError('"port" option should be >= 0 and < 65536: ' + port); | ||
throw new errors.RangeError('ERR_SOCKET_BAD_PORT'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the port
be passed as a parameter to the throw
here, and also on line 1475?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that would be nice 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ERR_SOCKET_BAD_PORT
definition in lib/internal/errors.js
does not handle a port argument. Should I refactor it to something like this?
E('ERR_SOCKET_BAD_PORT', (port) => {
const portMsg = port ? `: ${port}` : '';
return `Port${portMsg} should be > 0 and < 65536`;
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I commited the change to pass the port value in the 'ERR_SOCKET_BAD_PORT'
call in lib/net.js
. This will not be included in the err msg until we modify the E('ERR_SOCKET_BAD_PORT', 'Port should be > 0 and < 65536');
in lib/internal/errors.js
(see my above comment/question)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for your contribution. It looks pretty good overall. A few Error classes seemed to be mistaken though.
Besides that it would be nice to use common.expectsError(throwingFunction, options)
instead of assert.throws(throwingFunction, common.expectsError(options))
but this should not block the PR.
lib/net.js
Outdated
@@ -1018,21 +1020,25 @@ function lookupAndConnect(self, options) { | |||
var localPort = options.localPort; | |||
|
|||
if (localAddress && !cares.isIP(localAddress)) { | |||
throw new TypeError('"localAddress" option must be a valid IP: ' + | |||
localAddress); | |||
throw new errors.Error('ERR_INVALID_IP_ADDRESS', localAddress); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this changed to a Error
? It was a TypeError
before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually think not using TypeError
is appropriate here. I've never felt that TypeError
was a good fit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my bad. I corrected this, now the error types in lib/net.js have the correct value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jasnell i have already committed (some minutes ago) a change that preserve the error types as they were in lib/net.js
. So this is now a TypeError
as before. Should I re-change it?
const assertPort = () => { | ||
return common.expectsError({ | ||
code: 'ERR_SOCKET_BAD_PORT', | ||
type: Error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a RangeError
before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, this one should be a RangeError
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my bad. I corrected this, now the error types in lib/net.js have the correct value.
test/parallel/test-net-localerror.js
Outdated
localPort: 'foobar', | ||
}, /^TypeError: "localPort" option should be a number: foobar$/); | ||
localAddress: 'foobar', | ||
}, 'ERR_INVALID_IP_ADDRESS', Error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a TypeError
before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my bad. I corrected this, now the error types in lib/net.js have the correct value.
} | ||
if (!isLegalPort(port)) { | ||
throw new RangeError('"port" option should be >= 0 and < 65536: ' + port); | ||
throw new errors.RangeError('ERR_SOCKET_BAD_PORT', port); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error type must also be able to handle the provided port.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have made a change to include the port in the err msg if the port arg is passed to the error constructor.
lib/internal/errors.js
Outdated
portMsg = `:${port}`; | ||
} | ||
return `Port${portMsg} should be > 0 and < 65536`; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is more complicated then it has to be. I would rather have
E('ERR_SOCKET_BAD_PORT', 'Port should be > 0 and < 65536. Received %s.');
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed (commit: b336aa1)
Covert lib/net.js over to using lib/internal/errors.js Ref: nodejs#11273 I have not addressed the cases that use errnoException(), for reasons described in nodejsGH-12926 - Replace thrown errors in lib/net.js with errors from lib/internal/errors. The ERR_INVALID_OPT_VALUE error have been used in the Server.prototype.listen() method after a discussion in Ref: nodejs#14782 - Update tests according to the above modifications
- refactor the portTypeError and portRangeError assertions, by passing the expected call count to common.expectsError in test-net-connect-options-port.js (Each syncFailToConnect() call will call 4 or 2 times the doConnect() method, wich returns an array of size 6, so the call counts are 96 and 168 for portTypeError and portRangeError respectively) - refactor the connect() method in test-net-localerror.js, by removing the reduntant assert and use the common.expectsError() assertion - move require('../common') to the top in test-net-server-options.js
- refactor the valid types argument of ERR_INVALID_ARG_TYPE errors, to be a string instead of an array when the number of valid types equals 1, in lib/net.js
replace "listen options" with "options"
- Create a new error 'ERR_INVALID_FD_TYPE' in lib/internal/errors.js, following the corresponding discussion at Ref: nodejs#14782. This error should be thrown when a file descriptor type is not valid. - add test for the new err in test-internal-errors.js - update the error doc in errors.md - use the new err in createHandle() in lib/net.js - Add brackets {} in arrow function in test-net-localerror.js to match the typical source code's format.
- add missing test for the 'ERR_INVALID_FD_TYPE' err that is thrown from the net.Socket constructor - correct the err type from Error to TypeError
- correct 'ERR_INVALID_IP_ADDRESS' type to TypeError err in net.js - correct 'ERR_SOCKET_BAD_PORT' type to RangeError in net.js - correct 'ERR_INVALID_OPT_VALUE' type to Error in net.js - pass the port value to the the 'ERR_SOCKET_BAD_PORT' err in net.js
- Modify the ERR_SOCKET_BAD_PORT definition in internal/errors.js to include the specified port in the err msg, if the port arg is passed to the err constructor. - Add tests for ERR_SOCKET_BAD_PORT msg in test-internal-errors.js
- simplify the ERR_SOCKET_BAD_PORT error definition in errors.js by replacing the cb arg with the string: 'Port should be > 0 and < 65536. Received %s.' - update the ERR_SOCKET_BAD_PORT test in test-internal-errors.js - update the ERR_SOCKET_BAD_PORT constructor call in lib/dgram.js and lib/dns to include the actual port as the second arg - update the already existing ERR_SOCKET_BAD_PORT message assertion in test-dns.js, to include the actual port.
e1834d5
to
5a4e982
Compare
I went ahead and rebased the branch. |
@@ -1065,7 +1071,10 @@ function lookupAndConnect(self, options) { | |||
} | |||
|
|||
if (options.lookup && typeof options.lookup !== 'function') | |||
throw new TypeError('"lookup" option should be a function'); | |||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should likely be ERR_INVALID_OPTION_VALUE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are thrown errors for all the following 4 values in lib/net
lookupAndConnect
function :
function lookupAndConnect(self, options) {
// ...
options.port
options.localAddress
options.localPort
options.lookup
// ...
So I guess that for consistency, all the errors thrown for invalid values of the above vars should have a code of ERR_INVALID_OPTION_VALUE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked how we use mainly use this right now in the code base and it seems like ERR_INVALID_ARG_TYPE
is the right type here. We might improve those types in general later on further but I think this should not block the PR from being merged.
This is failing in CI: https://ci.nodejs.org/job/node-test-commit-linuxone/8827/nodes=rhel72-s390x/ |
Sry for being unresponsive. I was unavailable due to some hlth problem. I will look into the issues. |
@pmatzavin ... no worries. Hope you're feeling better. |
I am getting different results when running the tests locally. The CI failing test(parallel/test-net-socket-fd-error) passes in my local env. I haven't found yet, why this can be inconsistent. |
removed the test/parallel/test-net-socket-fd-error.js this test was added in the current PR but is not consistent. As the used fd mock value does not consistenly resolve to a fd type not equal to 'PIPE' and not equal to 'TCP'
I removed the failing test / file: This test was added by me in the current PR
by calling
but i could not find a fd value/number that will fit for this test. |
@pmatzavin I think only one review has to be addressed and it should be good to go. I will start a CI as soon as that is done. |
Running the tests again https://ci.nodejs.org/job/node-test-pull-request/10374/ |
CI before landing : https://ci.nodejs.org/job/node-test-pull-request/10717/ |
Landed in 7f55349 Note that there is still #15589 that we need to fix after this (See #14782 (review) regarding using |
Covert lib/net.js over to using lib/internal/errors.js - Replace thrown errors in lib/net.js with errors from lib/internal/errors. The ERR_INVALID_OPT_VALUE error have been used in the Server.prototype.listen() method - Update tests according to the above modifications PR-URL: #14782 Refs: #11273 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Covert lib/net.js over to using lib/internal/errors.js - Replace thrown errors in lib/net.js with errors from lib/internal/errors. The ERR_INVALID_OPT_VALUE error have been used in the Server.prototype.listen() method - Update tests according to the above modifications PR-URL: nodejs/node#14782 Refs: nodejs/node#11273 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Covert lib/net.js over to using lib/internal/errors.js
Ref: #11273
I have not addressed the cases that use errnoException(),
for reasons described in GH-12926
with errors from lib/internal/errors
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
lib/net, doc